import {ScannerType} from "./scanner"
class TagExpression{
    constructor(tagName, attrs, children, closeTagType){
        this.tag = tagName;
        this.attrs  = attrs;
        this.children = children;
        this.closeTagType = closeTagType;
    }
}
class TextExpression{
    constructor(text){
        this.text = text;
    }
}
class TemplateExpression{
    constructor(value){
        this.value = value;
    }
}
// if语法需要单独编译成一个树
class IfExpression{
    constructor(condition, block, key){
        this.condition = condition;
        this.key = key;
        this.block = block;
        Object.assign(this, block);
        this.alternate = [];
    }
}
export class Parser{
    constructor(tokens){
        this.tokens = tokens;
        this.position = 0;
        this.root = undefined;
        this.stacks = [];
        this.ifDirectives = ['v-if', 'v-else-if', 'v-else'];
        this.ifStacks = [];
    }
    get current(){
        return this.tokens[this.position];
    }
    next(){
        this.position++;
    }
    matchToken(type){
        const current = this.current;
        if (type === current.type){
            this.next();
            return current;
        }
        throw new Error(`不期望的token类型[${current.type}], 正确类型[${type}]`)
    }

    parse(){
        while(this.current.type !== ScannerType.END){
            this._parse();
        }
        this.matchToken(ScannerType.END);
        return this.root;
    }
    _parse(){
        switch(this.current.type){
            // <div @click='add'>
            // <child/>
            case ScannerType.OPENTAG:
                const tag = this.parseTag();
                if (!tag){
                    break;
                }
                if (!this.root){
                    this.root = tag; 
                }else{
                    if ((tag instanceof IfExpression && tag.key === 'v-if') || !(tag instanceof IfExpression)){
                        this.stacks[this.stacks.length-1].children.push(tag);
                    }
                }
                if (tag.closeTagType === ScannerType.CLOSETAG && tag.tag!=='input'){
                    this.stacks.push(tag);
                }
                break;
            // </div>
            case ScannerType.OPENSLASHTAG:
                {
                    const closeTagToken = this.matchToken(ScannerType.OPENSLASHTAG);
                    this.matchToken(ScannerType.CLOSETAG);

                    const tagName = closeTagToken.value;
                    const startTagName = this.stacks[this.stacks.length-1].tag;
                    if (startTagName === tagName){
                        this.stacks.pop();
                    }else{
                        throw new Error(`不匹配的tag名字 [${tagName}]-[${startTagName}]`)
                    }
                    
                    break;
                }
            case ScannerType.TEMPLATE:
                {
                    const template = this.matchToken(ScannerType.TEMPLATE).value;
                    this.stacks[this.stacks.length-1].children.push(new TemplateExpression(template));
                    break;
                }
            case ScannerType.TEXT:
                {
                    const text = this.matchToken(ScannerType.TEXT).value;
                    this.stacks[this.stacks.length-1].children.push(new TextExpression(text));

                    break;
                }
            default:
                throw new Error(`还不认识这种类型的[${this.current.type}]`)
            
        }
        
    }
    isIf(attrs){
        for(let i=0;i<attrs.length; i++){
            const {key} =  attrs[i]
            if(this.ifDirectives.includes(key)){
                return attrs[i];
            }
        }
        return false;
    }
    parseTag(){
        // <div> 
        // </div>
        const tagToken = this.matchToken(ScannerType.OPENTAG);
        const attrs = [];
        while (
            this.current.type !== ScannerType.CLOSETAG &&
            this.current.type !== ScannerType.CLOSESLASHTAG
        ){
            const attr = this.parseAttr();
            attrs.push(attr);
        }
        const ifDirective = this.isIf(attrs);
        let closeTagType = this.current.type;
        if (this.current.type === ScannerType.CLOSETAG){
            this.matchToken(ScannerType.CLOSETAG);
        }
        
        if ( 
            this.current.type === ScannerType.CLOSESLASHTAG 
        ){
            this.matchToken( ScannerType.CLOSESLASHTAG);
        }
        const tagExpression = new TagExpression(tagToken.value, attrs, [], closeTagType);
        if (!ifDirective){
            return tagExpression;
        }
        const {key, value} = ifDirective;
        const ifExpression = new IfExpression(value, tagExpression, key);
        if (key === 'v-if'){
            this.ifStacks.push(ifExpression);
        }else if (key === 'v-else-if'){
            if (this.ifStacks.length===0){
                throw new Error(`不能以 v-else-if 开头哦`)
            }
            this.ifStacks[this.ifStacks.length-1].alternate.push(ifExpression);
        }else if (key === 'v-else'){
            if (this.ifStacks.length===0){
                throw new Error(`不能以 v-else 开头哦`)
            }
            this.ifStacks[this.ifStacks.length-1].alternate.push(ifExpression);
        }
        return ifExpression;
        
        
    }
    parseAttr(){
        const attr = {
            key: '',
            hasValue: false
        };
        const attrKey = this.matchToken(ScannerType.ATTRKEY);
        attr.key = attrKey.value;
        if (this.current.type===ScannerType.EQUAL){
            attr.hasValue = true;
            const equal = this.matchToken(ScannerType.EQUAL);
            const attrValue = this.matchToken(ScannerType.STRING);
            attr.value = attrValue.value
        }
        return attr;
    }
}